package gocode

import (
	"bytes"
	"chainmaker.org/chainmaker/smarteditor/common"
	"chainmaker.org/chainmaker/smarteditor/container"
	"chainmaker.org/chainmaker/smarteditor/util"
	"context"
	"github.com/keegancsmith/rpc"
)

//autoCompleteRequest auto complete request data
type autoCompleteRequest struct {
	Filename           string
	Data               []byte
	Cursor             int
	Context            *packedContext
	Source             bool //use source importer
	Builtin            bool //propose completions for built-in functions and types
	IgnoreCase         bool //do case-insensitive matching
	UnimportedPackages bool //propose completions for standard library packages not explicitly imported
	FallbackToSource   bool //if importing a package fails, fallback to the source importer
}

//autoCompleteReply auto complete response data
type autoCompleteReply struct {
	Candidates []Candidate
	Len        int
}

type packedContext struct {
	Dir string
}

//AutoComplete send autocomplete request to go code server by tcp
func AutoComplete(fileAbsPath, fileDir string, data []byte, offset int, serverAddr string) ([]byte, error) {
	stopWatcher := util.NewDefaultStopWatcher()

	stopWatcher.Start("dial rpc")
	client, err := rpc.Dial(common.GoCodeSockType, serverAddr)
	if err != nil {
		return nil, err
	}
	defer client.Close()

	stopWatcher.StopLastAndStartNew("call")
	requestData := buildAutocompleteRequestData(fileAbsPath, fileDir, data, offset)
	var res autoCompleteReply

	err = client.Call(context.Background(), common.GoCodeServiceMethod, requestData, &res)
	if err != nil {
		return nil, err
	}

	stopWatcher.StopLastAndStartNew("marshal")
	responseByteBuffer := &bytes.Buffer{}
	err = jsonFormat(responseByteBuffer, res.Candidates, res.Len)
	if err != nil {
		return nil, err
	}
	stopWatcher.Stop()

	container.SC.Logger.Debugf("[AutoComplete] request success time cost:%s", stopWatcher.String())
	return responseByteBuffer.Bytes(), nil
}

func buildAutocompleteRequestData(fileNameAbsPath, filePath string, data []byte, offset int) *autoCompleteRequest {
	var reqData autoCompleteRequest
	reqData.Source = false
	reqData.Builtin = true
	reqData.IgnoreCase = false
	reqData.UnimportedPackages = false
	reqData.FallbackToSource = false
	reqData.Filename = fileNameAbsPath
	reqData.Data = data
	reqData.Cursor = offset
	reqData.Context = &packedContext{
		Dir: filePath,
	}
	return &reqData
}
